package scene

import (
	"clientDemo/service/asynccall"
	timer "clientDemo/service/asynccall"
	log2 "clientDemo/service/log"
	login_mod "clientDemo/service/login-mod"
	"clientDemo/service/modulemgr"
	"clientDemo/ui/fyne_ui/common"
	"clientDemo/ui/fyne_ui/scene/propert_scence"
	"clientDemo/ui/fyne_ui/scene/scene_widget"
	"clientDemo/ui/fyne_ui/scene/widget_tree"
	"clientDemo/ui/fyne_ui/theme"
	widget2 "clientDemo/ui/fyne_ui/widget"
	"clientDemo/ui/fyne_ui/widget/extend_widget"
	widgetcommon "clientDemo/ui/fyne_ui/widget/interface"
	wf "clientDemo/ui/fyne_ui/widget/widget_function"
	"clientDemo/utils"
	"encoding/xml"
	"fmt"
	"fyne.io/fyne/v2"
	app2 "fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/storage"
	fyneWidget "fyne.io/fyne/v2/widget"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var _theme fyne.Theme

type SceneModule struct {
	logger      *log.Logger
	loginModule login_mod.ILoginModule
	asyncModule timer.IAsyncCallModule

	mIsEditMode      bool                     //是否是设计模式
	mIsSizeMode      bool                     //是否改变大小
	mEditNode        widgetcommon.IWidgetItem //当前编辑的节点
	mOffsetPos       fyne.Position            //当前编辑的节点偏移量
	mOffsetPosGlobal fyne.Position            //当前编辑的节点偏移量

	mPropEditor *propert_scence.PropertiesEditor //属性编辑器
	mWidgetTree *widget_tree.WidgetTreeEditor    //控件树

	mMainWindow       fyne.Window                  //主窗口
	mRunButton        *scene_widget.RunButton      // 运行按钮
	mNewElementButton *scene_widget.NewButton      // 新建按钮
	mMenuController   *scene_widget.MenuController // 菜单控制器
	mCurrentXmlPath   string                       //当前打开的XML文件路径
}

func NewSceneModule() *SceneModule {
	return &SceneModule{
		mIsEditMode: true, // 默认设置为编辑模式
	}
}

func (m *SceneModule) Init(mm modulemgr.IModuleManager) (bool, error) {
	m.logger = log2.Logger
	var ok bool
	m.loginModule, ok = mm.GetModule(login_mod.Name).(login_mod.ILoginModule)
	m.asyncModule, ok = mm.GetModule(asynccall.Name).(asynccall.IAsyncCallModule)

	if !ok {
		return false, fmt.Errorf("failed to assert module to IConfigModule")
	}
	_theme = theme.NewTheme("./font/simhei.ttf")
	return true, nil
}
func (m *SceneModule) Run(mm modulemgr.IModuleManager) (bool, error) {
	isLogin := m.loginModule.CheckLoginStatus()
	m.CreateMainForm(isLogin)

	return true, nil
}
func (m *SceneModule) CreateMainForm(isLogin bool) {
	myApp := app2.New()
	myApp.Settings().SetTheme(_theme)
	m.InitIcon(myApp) // 添加图标
	m.MakeTray(myApp) // 添加系统托盘
	m.MainScene(myApp, isLogin)

	log.Printf("---------------这是UI协程ID：%v \n", utils.GetGoroutineID())
	myApp.Run()
}

func (m *SceneModule) ButtonHome(item widgetcommon.IWidgetItem, obj widgetcommon.IUserInfo) bool {
	obj2 := wf.GetChildWidgetByName(currentWidget, "HomeID")
	_ = obj2
	if obj2 == nil {
		return true
	}
	obj2.(*extend_widget.NewText).Text.Text = "HomeID00000000000000000"
	obj2.(*extend_widget.NewText).Refresh()
	log.Printf("---------------这是ButtonHome协程ID：%v \n", utils.GetGoroutineID())

	return true
}

// QuitApplication 退出应用程序
func (m *SceneModule) QuitApplication() {
	log.Println("正在退出应用程序...")
	// 可以在这里添加清理逻辑，比如保存数据等
	if m.mMainWindow != nil {
		m.mMainWindow.Close()
	}
	// 强制退出应用程序
	os.Exit(0)
}

// GetEditMode 获取当前编辑模式状态
func (m *SceneModule) GetEditMode() bool {
	return m.mIsEditMode
}

// NewFile 新建文件
func (m *SceneModule) NewFile() {
	log.Println("正在新建文件...")

	// 1. 清理当前场景资源
	m.cleanupCurrentScene()

	// 2. 重新初始化场景
	m.reinitializeScene()

	// 3. 重置编辑状态
	m.SetEditMode(true)

	log.Println("新建文件完成")
}

// OpenFile 打开文件
func (m *SceneModule) OpenFile() {
	log.Println("正在打开文件...")

	// 创建文件对话框
	fileDialog := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
		if err != nil {
			log.Printf("打开文件错误: %v", err)
			return
		}
		if reader == nil {
			log.Println("用户取消了文件选择")
			return
		}
		defer reader.Close()

		// 获取文件路径
		filePath := reader.URI().Path()
		log.Printf("选择的文件路径: %s", filePath)

		// 检查文件扩展名
		ext := filepath.Ext(filePath)
		if ext != ".xml" {
			log.Printf("警告: 选择的文件不是XML格式 (%s)", ext)
			// 显示警告对话框
			dialog.ShowInformation("文件格式警告",
				fmt.Sprintf("选择的文件不是XML格式 (%s)，可能无法正确加载。", ext),
				m.mMainWindow)
		}

		// 保存当前文件路径
		m.mCurrentXmlPath = filePath

		// 重新加载场景
		m.reloadSceneWithNewFile(filePath)

		// 显示成功加载提示
		dialog.ShowInformation("文件加载成功",
			fmt.Sprintf("已成功加载场景文件:\n%s", filePath),
			m.mMainWindow)
	}, m.mMainWindow)

	// 设置文件过滤器，只显示XML文件
	fileDialog.SetFilter(storage.NewExtensionFileFilter([]string{".xml"}))

	// 设置初始目录为程序运行的工作目录
	workDir, err := os.Getwd()
	if err != nil {
		// 如果获取工作目录失败，尝试使用用户主目录
		workDir, err = os.UserHomeDir()
		if err != nil {
			log.Printf("无法获取工作目录和用户主目录: %v", err)
		}
	}

	if err == nil {
		workURI := storage.NewFileURI(workDir)
		if listableURI, ok := workURI.(fyne.ListableURI); ok {
			fileDialog.SetLocation(listableURI)
			log.Printf("设置文件对话框初始目录为: %s", workDir)
		}
	}

	// 注意：Fyne的文件对话框会自动显示标题

	// 显示文件对话框
	fileDialog.Show()
}

// reloadSceneWithNewFile 使用新文件重新加载场景
func (m *SceneModule) reloadSceneWithNewFile(xmlPath string) {
	log.Printf("使用新文件重新加载场景: %s", xmlPath)

	// 1. 清理当前场景资源
	m.cleanupCurrentScene()

	// 2. 重新初始化场景，使用新的XML文件路径
	m.reinitializeSceneWithFile(xmlPath)

	// 3. 重置编辑状态
	m.SetEditMode(true)

	log.Println("文件加载完成")
}

// reinitializeSceneWithFile 使用指定文件重新初始化场景
func (m *SceneModule) reinitializeSceneWithFile(xmlPath string) {
	log.Printf("使用文件重新初始化场景: %s", xmlPath)

	// 重新创建空的控件容器
	emptyWidget := widget2.CreatWidgetContainerByName(widget2.Default_WidgetContainer_Name, fyne.NewSize(float32(common.LoginGUIWidth), float32(common.LoginGUIHeight)))
	currentWidget = emptyWidget.(widgetcommon.IWidgetItem)
	emptyWidget.SetName("root")

	// 重新加载皮肤XML
	_ = widget2.NewSkinXmlParser("./skin/WidgetTemplate/WidgetSkin.xml")

	// 使用新的XML文件路径创建场景解析器
	sceneXml = widget2.NewSceneXmlParser(xmlPath, emptyWidget)

	// 重新创建属性编辑器和控件树
	m.mWidgetTree = widget_tree.NewWidgetTreeEditor("列表")
	m.mPropEditor = propert_scence.NewPropertiesEditor("属性")

	// 更新控件树
	m.mWidgetTree.UpdateTreeItem(sceneXml.RootNode)

	// 重新设置触摸回调
	emptyWidget.SetTouchBeganCallback(m.TouchBeganCallback)
	emptyWidget.SetTouchMovedCallback(m.TouchMovedCallback)
	emptyWidget.SetTouchEndedCallback(m.TouchEndedCallback)

	// 重新注册按钮回调
	widget2.RegeditButtonCallBack("Button_Main", m.ButtonHome)

	// 重新设置主窗口内容
	m.refreshMainWindowContent()

	log.Println("场景重新初始化完成")
}

// cleanupCurrentScene 清理当前场景资源
func (m *SceneModule) cleanupCurrentScene() {
	log.Println("清理当前场景资源...")

	// 清理编辑节点
	m.mEditNode = nil

	// 清理属性编辑器
	if m.mPropEditor != nil {
		// 这里可以添加属性编辑器的清理逻辑
		log.Println("清理属性编辑器")
	}

	// 清理控件树
	if m.mWidgetTree != nil {
		// 这里可以添加控件树的清理逻辑
		log.Println("清理控件树")
	}

	// 清理全局变量
	if currentWidget != nil {
		// 清理当前控件
		currentWidget = nil
	}

	if sceneXml != nil {
		// 清理场景XML解析器
		sceneXml = nil
	}

	// 清理注册的回调函数
	widget2.ClearButtonCallBacks()

	log.Println("场景资源清理完成")
}

// reinitializeScene 重新初始化场景
func (m *SceneModule) reinitializeScene() {
	log.Println("重新初始化场景...")

	// 重新创建空的控件容器
	emptyWidget := widget2.CreatWidgetContainerByName(widget2.Default_WidgetContainer_Name, fyne.NewSize(float32(common.LoginGUIWidth), float32(common.LoginGUIHeight)))
	currentWidget = emptyWidget.(widgetcommon.IWidgetItem)
	emptyWidget.SetName("root")

	// 重新加载皮肤XML
	_ = widget2.NewSkinXmlParser("./skin/WidgetTemplate/WidgetSkin.xml")
	sceneXml = widget2.NewSceneXmlParser("./skin/MainScene/MainScene.xml", emptyWidget)

	// 重新创建属性编辑器和控件树
	m.mWidgetTree = widget_tree.NewWidgetTreeEditor("列表")
	m.mPropEditor = propert_scence.NewPropertiesEditor("属性")

	// 更新控件树
	m.mWidgetTree.UpdateTreeItem(sceneXml.RootNode)

	// 重新设置触摸回调
	emptyWidget.SetTouchBeganCallback(m.TouchBeganCallback)
	emptyWidget.SetTouchMovedCallback(m.TouchMovedCallback)
	emptyWidget.SetTouchEndedCallback(m.TouchEndedCallback)

	// 重新注册按钮回调
	widget2.RegeditButtonCallBack("Button_Main", m.ButtonHome)

	// 重新设置主窗口内容
	m.refreshMainWindowContent()

	log.Println("场景重新初始化完成")
}

// refreshMainWindowContent 刷新主窗口内容
func (m *SceneModule) refreshMainWindowContent() {
	if m.mMainWindow == nil {
		return
	}

	// 重新创建分割容器
	split := container.NewHSplit(
		currentWidget.(fyne.CanvasObject),
		container.NewAppTabs(
			m.mPropEditor.GetTabItem(),
			m.mWidgetTree.GetTabItem(),
			loadInformationTab(),
		),
	)
	split.SetOffset(0.80)

	// 重新创建菜单栏容器
	menuBarHeight := float32(24)
	menuBarContainer := container.NewWithoutLayout()
	menuBarContainer.Resize(fyne.NewSize(float32(common.LoginGUIWidth), menuBarHeight))

	// 重新设置运行按钮
	buttonSize := fyne.NewSize(menuBarHeight, menuBarHeight)
	m.mRunButton.Resize(buttonSize)
	m.mRunButton.Move(fyne.NewPos(400, 0))
	menuBarContainer.AddObject(m.mRunButton)

	menuBarWrapper := container.NewPadded(menuBarContainer)
	separator := fyneWidget.NewSeparator()

	// 重新创建主容器
	mainContainer := container.New(
		&customLayout{},
		menuBarWrapper,
		separator,
		container.NewPadded(split),
	)

	// 设置主窗口内容
	m.mMainWindow.SetContent(mainContainer)
}

// SetEditMode 设置编辑模式
func (m *SceneModule) SetEditMode(isEdit bool) {
	m.mIsEditMode = isEdit
	if !isEdit {
		m.mEditNode = nil
	}
	widgetcommon.IsEditMode = isEdit

	// 同步菜单的编辑状态
	if m.mMenuController != nil {
		m.mMenuController.SetEditModeInternal(isEdit)
	}

	// 同步运行按钮的编辑状态
	if m.mRunButton != nil {
		m.mRunButton.SetEditMode(isEdit)
	}

	fmt.Printf("编辑模式已设置为: %v\n", isEdit)
}

// SaveThis 保存当前文件
func (m *SceneModule) SaveThis() {
	log.Println("正在保存当前文件...")

	if m.mCurrentXmlPath == "" {
		// 如果没有当前文件路径，直接调用另存为功能
		log.Println("当前没有文件路径，自动切换到另存为功能")
		m.SaveOther()
		return
	}

	// 执行保存逻辑
	success := m.performSaveToFile(m.mCurrentXmlPath)
	if success {
		dialog.ShowInformation("保存成功",
			fmt.Sprintf("文件已保存到:\n%s", m.mCurrentXmlPath),
			m.mMainWindow)
	} else {
		dialog.ShowError(fmt.Errorf("保存失败"), m.mMainWindow)
	}
}

// SaveOther 另存为文件
func (m *SceneModule) SaveOther() {
	log.Println("正在另存为文件...")

	// 创建文件保存对话框
	fileDialog := dialog.NewFileSave(func(writer fyne.URIWriteCloser, err error) {
		if err != nil {
			log.Printf("保存文件错误: %v", err)
			dialog.ShowError(err, m.mMainWindow)
			return
		}
		if writer == nil {
			log.Println("用户取消了文件保存")
			return
		}
		defer writer.Close()

		// 获取文件路径
		filePath := writer.URI().Path()
		log.Printf("保存文件路径: %s", filePath)

		// 执行保存逻辑
		success := m.performSaveToFile(filePath)
		if success {
			// 更新当前文件路径
			m.mCurrentXmlPath = filePath
			dialog.ShowInformation("保存成功",
				fmt.Sprintf("文件已保存到:\n%s", filePath),
				m.mMainWindow)
		} else {
			dialog.ShowError(fmt.Errorf("保存失败"), m.mMainWindow)
		}
	}, m.mMainWindow)

	// 设置文件过滤器，只保存XML文件
	fileDialog.SetFilter(storage.NewExtensionFileFilter([]string{".xml"}))

	// 设置默认文件名
	if m.mCurrentXmlPath != "" {
		// 如果有当前文件，使用当前文件名作为默认名
		fileName := filepath.Base(m.mCurrentXmlPath)
		fileDialog.SetFileName(fileName)
	} else {
		// 如果没有当前文件，使用默认名称
		fileDialog.SetFileName("scene.xml")
	}

	// 设置初始目录为程序工作目录
	workDir, err := os.Getwd()
	if err == nil {
		workURI := storage.NewFileURI(workDir)
		if listableURI, ok := workURI.(fyne.ListableURI); ok {
			fileDialog.SetLocation(listableURI)
		}
	}

	// 显示文件保存对话框
	fileDialog.Show()
}

// performSaveToFile 执行保存到指定文件
func (m *SceneModule) performSaveToFile(filePath string) bool {
	log.Printf("执行保存到文件: %s", filePath)

	if filePath == "" {
		log.Println("错误: 文件路径为空")
		return false
	}
	filePath = filepath.Clean(filePath)
	log.Printf("规范化后的文件路径: %s", filePath)

	// 定义与目标格式匹配的结构
	type Property struct {
		XMLName xml.Name `xml:"Property"`
		Key     string   `xml:"Key,attr"`
		Value   string   `xml:"Value,attr"`
	}
	type LoadSkin struct {
		XMLName xml.Name `xml:"LoadSkin"`
		Skin    string   `xml:"Skin,attr"`
	}
	type Widget struct {
		XMLName      xml.Name   `xml:"Widget"`
		Name         string     `xml:"Name,attr"`
		SkinTempName string     `xml:"SkinTempName,attr,omitempty"`
		Properties   []Property `xml:"Property,omitempty"`
		Widgets      []Widget   `xml:"Widget,omitempty"`
	}
	type Root struct {
		XMLName    xml.Name   `xml:"root"`
		LoadSkin   LoadSkin   `xml:"LoadSkin"`
		Properties []Property `xml:"Property"`
		Widgets    []Widget   `xml:"Widget"`
	}

	// 构造根对象
	root := Root{
		XMLName:  xml.Name{Local: "root"},
		LoadSkin: LoadSkin{Skin: sceneXml.LoadSkin.Skin},
		Properties: []Property{
			{Key: "Title", Value: sceneXml.Title},
			{Key: "MainWidth", Value: fmt.Sprintf("%d", sceneXml.MainWidth)},
			{Key: "MainHeight", Value: fmt.Sprintf("%d", sceneXml.MainHeight)},
		},
	}

	// 递归构建Widget树
	var build func(node widgetcommon.IWidgetItem) Widget
	build = func(node widgetcommon.IWidgetItem) Widget {
		w := Widget{XMLName: xml.Name{Local: "Widget"}, Name: node.GetName()}
		if ui, ok := node.(widgetcommon.IUserInfo); ok {
			ui.ForEachProperty(func(key, value string) {
				w.Properties = append(w.Properties, Property{Key: key, Value: value})
			})
			w.SkinTempName = ui.GetSkinTempName()
		}
		node.ForEach(func(child widgetcommon.IWidgetItem) bool {
			w.Widgets = append(w.Widgets, build(child))
			return false
		})
		return w
	}

	// 顶层Widget为RootNode的直接子节点（不再包一层空Widget）
	sceneXml.RootNode.ForEach(func(node widgetcommon.IWidgetItem) bool {
		root.Widgets = append(root.Widgets, build(node))
		return false
	})

	// 编码XML
	var xmlOutput strings.Builder
	xmlOutput.WriteString(`<?xml version="1.0" encoding="utf-8" ?>` + "\n")
	enc := xml.NewEncoder(&xmlOutput)
	enc.Indent("", "    ")
	if err := enc.Encode(root); err != nil {
		log.Printf("错误: 编码XML失败 - %v", err)
		return false
	}
	if err := enc.Flush(); err != nil {
		log.Printf("错误: 刷新XML编码器失败 - %v", err)
		return false
	}

	// 后处理：将无子节点的元素转换为自闭合写法
	out := xmlOutput.String()
	reProp := regexp.MustCompile(`<Property([^>]*)></Property>`)
	out = reProp.ReplaceAllString(out, `<Property$1 />`)
	reSkin := regexp.MustCompile(`<LoadSkin([^>]*)></LoadSkin>`)
	out = reSkin.ReplaceAllString(out, `<LoadSkin$1 />`)

	// 写入文件
	file, err := os.Create(filePath)
	if err != nil {
		log.Printf("错误: 创建文件失败 - %v", err)
		return false
	}
	defer file.Close()
	if _, err := file.WriteString(out); err != nil {
		log.Printf("错误: 写入文件失败 - %v", err)
		return false
	}
	log.Printf("文件保存成功: %s", filePath)
	return true
}
